#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

int send_and_recieve(int socket, char message[], int byte_count) {
	char count = (char) byte_count;
	//send size of number
	if (send(socket, &count, sizeof(count), 0) != sizeof(count)) {
		perror("Number send");
		close(socket);
		exit(-1);
	}
	//send number
	if (send(socket, message, byte_count, 0) != byte_count) {
		perror("Number send");
		close(socket);
		exit(-2);
	}
	int i;
	char response[8];
	int recieved = 0;
	//get each byte separately
	for (recieved = 0; recieved < byte_count; recieved++) {
		if (recv(socket, response + recieved, 1, 0) <= 0) {
			perror("recv");
			exit(-3);
		}
	}
	if (byte_count == 1) {
		printf("Recieved: %d\n", (int)response[0]);
	} else if (byte_count == 2) {
		int16_t result;
		memcpy(&result, response, 2);
		result = ntohs(result);
		printf("Recieved: %hd\n", result);
	} else if (byte_count == 4) {
		int32_t result;
		memcpy(&result, response, 4);
		result = ntohl(result);
		printf("Recieved: %d\n", result);
	} else if (byte_count == 8) {
		uint64_t result;
		uint32_t more_significant, less_significant;
		memcpy(&more_significant, response, 4);
		memcpy(&less_significant, response + 4, 4);
		more_significant = ntohl(more_significant);
		less_significant = ntohl(less_significant);
		result = (((uint64_t)more_significant) << 32) + less_significant;
		printf("Recieved: %lld\n", result);
	}
}

int main(int argc, char ** argv) {
	if (argc != 3) {
		perror("Wrong number of parameters.\nUsage: ./client <ip_address> <port_number>");
		return -1;
	}
	
	struct sockaddr_in server_address;
	int fd, len;
	fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd < 0) {
		perror("Socket opening");
		return -2;
	}
	
	bzero((char *)&server_address, sizeof(server_address));
	server_address.sin_family = AF_INET;
	server_address.sin_addr.s_addr = inet_addr(argv[1]);
	server_address.sin_port = htons(atoi(argv[2]));
	
	if (connect(fd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) {
		perror("Connect");
		close(fd);
		return -3;
	}
	
	/*char one_byte = 123;
	int16_t two_byte = 12345;
	int32_t four_byte = 123456789;
	int64_t eight_byte = 12345678910111213;*/
	srand(time(NULL));
	char one_byte = rand()%256;
	int16_t two_byte = rand();
	int32_t four_byte = rand()*rand();
	int64_t eight_byte = 1000000000*rand()*rand();
	printf("%d %hd %d %lld\n", one_byte, two_byte, four_byte, eight_byte);
	
	char message[8];//array of single bytes to send
	
	message[0] = one_byte;
	printf("Sending %d\n", (int)message[0]);
	send_and_recieve(fd, message, 1);
	
	two_byte = htons(two_byte);
	memcpy(message, &two_byte, 2);
	printf("Sending %hd\n", ntohs(two_byte));
	send_and_recieve(fd, message, 2);
	
	four_byte = htonl(four_byte);
	memcpy(message, &four_byte, 4);
	printf("Sending %d\n", ntohl(four_byte));
	send_and_recieve(fd, message, 4);
	
	int32_t more_significant, less_significant;
	more_significant = htonl((uint32_t)(eight_byte >> 32) & 0xFFFFFFFF);
	less_significant = htonl((uint32_t)eight_byte & 0xFFFFFFFF);
	printf("Sending %lld\n", eight_byte);
	memcpy(message, &more_significant, 4);
	memcpy(message + 4, &less_significant, 4);
	send_and_recieve(fd, message, 8);	
	
	close(fd);
	return 0;	
}
